source('../env.R')

Select species

These are all the species currently available from the eBird Status and Trends data product Sullivan and Kelling. (2009). https://science.ebird.org/en/status-and-trends/species#columb2

species_available = c("Streptopelia decaocto",
"Streptopelia semitorquata",
"Streptopelia capicola",
"Streptopelia tranquebarica",
"Spilopelia chinensis",
"Macropygia phasianella",
"Chalcophaps indica",
"Ocyphaps lophotes",
"Geopelia humeralis",
"Columbina inca",
"Columbina passerina",
"Columbina minuta",
"Columbina talpacoti",
"Columbina buckleyi",
"Columbina squammata",
"Columbina picui",
"Claravis pretiosa",
"Geotrygon montana",
"Leptotila verreauxi",
"Leptotila jamaicensis",
"Leptotila cassinii",
"Leptotila plumbeiceps",
"Zentrygon costaricensis",
"Zentrygon lawrencii",
"Zentrygon albifacies",
"Zentrygon chiriquensis",
"Zenaida meloda",
"Zenaida asiatica",
"Zenaida aurita",
"Zenaida auriculata",
"Zenaida macroura",
"Treron affinis",
"Treron phoenicopterus",
"Treron sieboldii",
"Treron formosae",
"Ducula aenea",
"Hemiphaga novaeseelandiae",
"Columba livia",
"Columba guinea",
"Columba oenas",
"Columba palumbus",
"Patagioenas cayennensis",
"Patagioenas speciosa",
"Patagioenas squamosa",
"Patagioenas picazuro",
"Patagioenas corensis",
"Patagioenas maculosa",
"Patagioenas leucocephala",
"Patagioenas flavirostris",
"Patagioenas fasciata",
"Patagioenas araucana",
"Patagioenas subvinacea",
"Patagioenas nigrirostris",
"Streptopelia turtur",
"Streptopelia orientalis")

length(species_available)
[1] 55

Filter against library list, as not everything on website is availble in library

species_available = ebirdst_runs$scientific_name[ebirdst_runs$scientific_name %in% species_available]
species_available
 [1] "Geopelia humeralis"         "Patagioenas fasciata"       "Macropygia phasianella"     "Patagioenas araucana"       "Columbina passerina"       
 [6] "Columba palumbus"           "Ocyphaps lophotes"          "Zenaida auriculata"         "Streptopelia decaocto"      "Columbina inca"            
[11] "Zenaida macroura"           "Hemiphaga novaeseelandiae"  "Streptopelia orientalis"    "Patagioenas picazuro"       "Columbina picui"           
[16] "Patagioenas flavirostris"   "Streptopelia tranquebarica" "Streptopelia semitorquata"  "Streptopelia capicola"      "Columba livia"             
[21] "Columbina talpacoti"        "Patagioenas squamosa"       "Patagioenas nigrirostris"   "Columba guinea"             "Spilopelia chinensis"      
[26] "Zenaida meloda"             "Patagioenas leucocephala"   "Leptotila verreauxi"        "Zenaida asiatica"           "Treron phoenicopterus"     
[31] "Zenaida aurita"            

First check that is no knarly taxonomic mapping required for any of these species:

taxonmomic_mapping = read_csv(filename(TAXONOMY_OUTPUT_DIR, 'taxonomy_mapping.csv'))
Rows: 438 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): species_name, birdlife_common_name, ebird_common_name, ebird_species_name, jetz_species_name
dbl (2): birdlife_id, ebird_id
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Species with 1 eBird taxa, and multiple Birdlife taxa will reuqire the ranges of the Birdlife taxa to be combined.

taxonmomic_mapping[taxonmomic_mapping$ebird_species_name %in% species_available,] %>%
  group_by(ebird_species_name) %>% 
  summarise(number_of_birdlife_species = n(), birdlife_species_names = paste(species_name, collapse = ",")) %>%
  filter(number_of_birdlife_species > 1)
  • Patagioenas fasciata, will need the range of Patagioenas fasciata and Patagioenas albilinea combined.

  • Spilopelia chinensis, will need the range of Spilopelia chinensis, Spilopelia suratensis, and Patagioenas albipennis combined.

Check whether we need to map eBird species names to Birdlife

taxonmomic_mapping[taxonmomic_mapping$ebird_species_name %in% species_available,] %>%
  filter(ebird_species_name != species_name) 

Species with 1 Birdlife taxa, and multiple eBird taxa will, would mean that we would have cities with no records but potentially have presence test data. We should avoid these species.

taxonmomic_mapping[taxonmomic_mapping$ebird_species_name %in% species_available,] %>%
  group_by(species_name) %>% 
  summarise(number_of_ebird_species = n(), ebird_species_names = paste(ebird_species_name, collapse = ",")) %>%
  filter(number_of_ebird_species > 1)
test_species = species_available

Create regional pool data

regional_pool_data_input = read_csv(filename(BIRDLIFE_WORKING_OUTPUT_DIR, 'urban_distributions.csv'))
Rows: 7215 Columns: 6── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): species_name, city_name, origin, seasonal, presence
dbl (1): city_id
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Join ranges up

regional_pool_data_input$species_name[regional_pool_data_input$species_name %in% c('Spilopelia suratensis', 'Patagioenas albipennis')] = 'Spilopelia chinensis'
regional_pool_data_input$species_name[regional_pool_data_input$species_name %in% c('Patagioenas albilinea')] = 'Patagioenas fasciata'

regional_pool_data = regional_pool_data_input %>% group_by(species_name, city_id, city_name) %>% summarise() %>% filter(species_name %in% test_species)
`summarise()` has grouped output by 'species_name', 'city_id'. You can override using the `.groups` argument.
regional_pool_data[regional_pool_data$city_name == 'Medellín',]

Create city to pigeon data

Get number of checklists and total effort in each city

urban_checklists = read_csv(filename(EBIRD_WORKING_OUTPUT_DIR, 'urban_checklists.csv'))
Rows: 3542050 Columns: 6── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (3): checklist_id, locality_id, city_name
dbl  (2): city_id, duration
date (1): obs_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
urban_summary = urban_checklists %>% group_by(city_id, city_name) %>% summarise(total_city_checklists = n(), total_city_effort = sum(duration))
`summarise()` has grouped output by 'city_id'. You can override using the `.groups` argument.
urban_summary

For each of our test species, find the number of checklists and total effort in each city

urban_columbidae_records_raw = read_csv(filename(EBIRD_WORKING_OUTPUT_DIR, 'urban_columbidae.csv'))
Rows: 2593785 Columns: 8── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): observation_count, checklist_id, city_name, species_name, common_name
dbl (3): number_observers, city_id, duration
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
urban_columbidae_records_raw[urban_columbidae_records_raw$city_name == 'Manchester',]

Join the total city data to each pigeon record

urban_columbidae_records = left_join(urban_columbidae_summary, urban_summary)
Joining, by = c("city_id", "city_name")
head(urban_columbidae_records)

We also want records for each city that could have that pigeon (e.g. in regional pool range) but has no eBird records

urban_columbidae_absence_records_part1 = left_join(regional_pool_data, urban_summary)
Joining, by = c("city_id", "city_name")

urban_columbidae_absence_records_part1$total_presence_checklists = 0
urban_columbidae_absence_records_part1$total_presence_effort = 0

urban_columbidae_absence_records = urban_columbidae_absence_records_part1[!is.na(urban_columbidae_absence_records_part1$total_city_checklists),]
urban_columbidae_absence_records
all_columbidae_around_cities = rbind(urban_columbidae_records, urban_columbidae_absence_records) %>%
  group_by(city_id, city_name, species_name, total_city_checklists, total_city_effort) %>%
  summarise(total_presence_checklists = sum(total_presence_checklists), total_presence_effort = sum(total_presence_effort)) %>%
  arrange(city_id, species_name)
`summarise()` has grouped output by 'city_id', 'city_name', 'species_name', 'total_city_checklists'. You can override using the `.groups` argument.

all_columbidae_around_cities$checklist_ratio = all_columbidae_around_cities$total_presence_checklists / all_columbidae_around_cities$total_city_checklists
all_columbidae_around_cities$effort_ratio = all_columbidae_around_cities$total_presence_effort / all_columbidae_around_cities$total_city_effort

all_columbidae_around_cities

Finally join our our test data result to show predicted abundance, remove any NA abundance as there is insufficent data in these places for a prediction.

Plot to see Expected test abundance vs checklists

n = ((Z * Z) * p * (1−p)) / (E * E)

(e.g., 99% corresponds to Z≈2.576Z≈2.576).

So for present = more than 5% of checklists.

p is the estimated probability of success (the proportion of checklists where the species is present). E is the margin of error (half the width of the confidence interval).

(2.576^2 * 0.95 * 0.05) / 0.01^2
[1] 3151.994
plot_city_species = function(city_id) {
  city_name = urban_summary$city_name[urban_summary$city_id == city_id]
  total_checklists = urban_summary$total_city_checklists[urban_checklists$city_id == city_id]
  
  ggplot(columbidae[columbidae$city_id == city_id,], aes(x = species_name, y = checklist_ratio * 100, fill = expected_present)) + 
    geom_bar(stat = "identity") + 
    geom_text(aes(label = round(max_abundance, 2))) + 
    theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) + 
    xlab('Species name') + ylab('% of Checklist present') + 
    facet_wrap(~city_id) + 
    geom_hline(yintercept=5, linetype='dotted', col = 'red') +
    labs(title = paste(city_name, total_checklists))
}
plot_city_species(1)

plot_city_species(10)

plot_city_species(14)

plot_city_species(21)

plot_city_species(155)

plot_city_species(7932)

plot_city_species(4328)

plot_city_species(1919)

Sullivan, C. L. Wood, B. L., and S. Kelling. 2009. “eBird: A Citizen-Based Bird Observation Network in the Biological Sciences.” 142 (10): 2282–92. https://doi.org/10.1016/j.biocon.2009.05.006.
LS0tCnRpdGxlOiAiR2VuZXJhdGUgcHJlc2VuY2UgdGVzdCBkYXRhIHVzaW5nIGVCaXJkIFN0YXR1cyAmIFRyZW5kcyIKb3V0cHV0OiBodG1sX25vdGVib29rCmJpYmxpb2dyYXBoeTogLi4vcmVmLmJpYiAKLS0tCgpgYGB7cn0Kc291cmNlKCcuLi9lbnYuUicpCmBgYAoKIyBTZWxlY3Qgc3BlY2llcwpUaGVzZSBhcmUgYWxsIHRoZSBzcGVjaWVzIGN1cnJlbnRseSBhdmFpbGFibGUgZnJvbSB0aGUgZUJpcmQgU3RhdHVzIGFuZCBUcmVuZHMgZGF0YSBwcm9kdWN0IEBlQmlyZDIwMjMuCmh0dHBzOi8vc2NpZW5jZS5lYmlyZC5vcmcvZW4vc3RhdHVzLWFuZC10cmVuZHMvc3BlY2llcyNjb2x1bWIyCgoKYGBge3J9CnNwZWNpZXNfYXZhaWxhYmxlID0gYygiU3RyZXB0b3BlbGlhIGRlY2FvY3RvIiwKIlN0cmVwdG9wZWxpYSBzZW1pdG9ycXVhdGEiLAoiU3RyZXB0b3BlbGlhIGNhcGljb2xhIiwKIlN0cmVwdG9wZWxpYSB0cmFucXVlYmFyaWNhIiwKIlNwaWxvcGVsaWEgY2hpbmVuc2lzIiwKIk1hY3JvcHlnaWEgcGhhc2lhbmVsbGEiLAoiQ2hhbGNvcGhhcHMgaW5kaWNhIiwKIk9jeXBoYXBzIGxvcGhvdGVzIiwKIkdlb3BlbGlhIGh1bWVyYWxpcyIsCiJDb2x1bWJpbmEgaW5jYSIsCiJDb2x1bWJpbmEgcGFzc2VyaW5hIiwKIkNvbHVtYmluYSBtaW51dGEiLAoiQ29sdW1iaW5hIHRhbHBhY290aSIsCiJDb2x1bWJpbmEgYnVja2xleWkiLAoiQ29sdW1iaW5hIHNxdWFtbWF0YSIsCiJDb2x1bWJpbmEgcGljdWkiLAoiQ2xhcmF2aXMgcHJldGlvc2EiLAoiR2VvdHJ5Z29uIG1vbnRhbmEiLAoiTGVwdG90aWxhIHZlcnJlYXV4aSIsCiJMZXB0b3RpbGEgamFtYWljZW5zaXMiLAoiTGVwdG90aWxhIGNhc3NpbmlpIiwKIkxlcHRvdGlsYSBwbHVtYmVpY2VwcyIsCiJaZW50cnlnb24gY29zdGFyaWNlbnNpcyIsCiJaZW50cnlnb24gbGF3cmVuY2lpIiwKIlplbnRyeWdvbiBhbGJpZmFjaWVzIiwKIlplbnRyeWdvbiBjaGlyaXF1ZW5zaXMiLAoiWmVuYWlkYSBtZWxvZGEiLAoiWmVuYWlkYSBhc2lhdGljYSIsCiJaZW5haWRhIGF1cml0YSIsCiJaZW5haWRhIGF1cmljdWxhdGEiLAoiWmVuYWlkYSBtYWNyb3VyYSIsCiJUcmVyb24gYWZmaW5pcyIsCiJUcmVyb24gcGhvZW5pY29wdGVydXMiLAoiVHJlcm9uIHNpZWJvbGRpaSIsCiJUcmVyb24gZm9ybW9zYWUiLAoiRHVjdWxhIGFlbmVhIiwKIkhlbWlwaGFnYSBub3ZhZXNlZWxhbmRpYWUiLAoiQ29sdW1iYSBsaXZpYSIsCiJDb2x1bWJhIGd1aW5lYSIsCiJDb2x1bWJhIG9lbmFzIiwKIkNvbHVtYmEgcGFsdW1idXMiLAoiUGF0YWdpb2VuYXMgY2F5ZW5uZW5zaXMiLAoiUGF0YWdpb2VuYXMgc3BlY2lvc2EiLAoiUGF0YWdpb2VuYXMgc3F1YW1vc2EiLAoiUGF0YWdpb2VuYXMgcGljYXp1cm8iLAoiUGF0YWdpb2VuYXMgY29yZW5zaXMiLAoiUGF0YWdpb2VuYXMgbWFjdWxvc2EiLAoiUGF0YWdpb2VuYXMgbGV1Y29jZXBoYWxhIiwKIlBhdGFnaW9lbmFzIGZsYXZpcm9zdHJpcyIsCiJQYXRhZ2lvZW5hcyBmYXNjaWF0YSIsCiJQYXRhZ2lvZW5hcyBhcmF1Y2FuYSIsCiJQYXRhZ2lvZW5hcyBzdWJ2aW5hY2VhIiwKIlBhdGFnaW9lbmFzIG5pZ3Jpcm9zdHJpcyIsCiJTdHJlcHRvcGVsaWEgdHVydHVyIiwKIlN0cmVwdG9wZWxpYSBvcmllbnRhbGlzIikKCmxlbmd0aChzcGVjaWVzX2F2YWlsYWJsZSkKYGBgCgpGaWx0ZXIgYWdhaW5zdCBsaWJyYXJ5IGxpc3QsIGFzIG5vdCBldmVyeXRoaW5nIG9uIHdlYnNpdGUgaXMgYXZhaWxibGUgaW4gbGlicmFyeQpgYGB7cn0Kc3BlY2llc19hdmFpbGFibGUgPSBlYmlyZHN0X3J1bnMkc2NpZW50aWZpY19uYW1lW2ViaXJkc3RfcnVucyRzY2llbnRpZmljX25hbWUgJWluJSBzcGVjaWVzX2F2YWlsYWJsZV0Kc3BlY2llc19hdmFpbGFibGUKYGBgCgojIyBGaXJzdCBjaGVjayB0aGF0IGlzIG5vIGtuYXJseSB0YXhvbm9taWMgbWFwcGluZyByZXF1aXJlZCBmb3IgYW55IG9mIHRoZXNlIHNwZWNpZXM6CmBgYHtyfQp0YXhvbm1vbWljX21hcHBpbmcgPSByZWFkX2NzdihmaWxlbmFtZShUQVhPTk9NWV9PVVRQVVRfRElSLCAndGF4b25vbXlfbWFwcGluZy5jc3YnKSkKYGBgCgpTcGVjaWVzIHdpdGggMSBlQmlyZCB0YXhhLCBhbmQgbXVsdGlwbGUgQmlyZGxpZmUgdGF4YSB3aWxsIHJldXFpcmUgdGhlIHJhbmdlcyBvZiB0aGUgQmlyZGxpZmUgdGF4YSB0byBiZSBjb21iaW5lZC4gCmBgYHtyfQp0YXhvbm1vbWljX21hcHBpbmdbdGF4b25tb21pY19tYXBwaW5nJGViaXJkX3NwZWNpZXNfbmFtZSAlaW4lIHNwZWNpZXNfYXZhaWxhYmxlLF0gJT4lCiAgZ3JvdXBfYnkoZWJpcmRfc3BlY2llc19uYW1lKSAlPiUgCiAgc3VtbWFyaXNlKG51bWJlcl9vZl9iaXJkbGlmZV9zcGVjaWVzID0gbigpLCBiaXJkbGlmZV9zcGVjaWVzX25hbWVzID0gcGFzdGUoc3BlY2llc19uYW1lLCBjb2xsYXBzZSA9ICIsIikpICU+JQogIGZpbHRlcihudW1iZXJfb2ZfYmlyZGxpZmVfc3BlY2llcyA+IDEpCmBgYAoKKiAqUGF0YWdpb2VuYXMgZmFzY2lhdGEqLCB3aWxsIG5lZWQgdGhlIHJhbmdlIG9mIFBhdGFnaW9lbmFzIGZhc2NpYXRhIGFuZCBQYXRhZ2lvZW5hcyBhbGJpbGluZWEgY29tYmluZWQuCgoqICpTcGlsb3BlbGlhIGNoaW5lbnNpcyosIHdpbGwgbmVlZCB0aGUgcmFuZ2Ugb2YgU3BpbG9wZWxpYSBjaGluZW5zaXMsIFNwaWxvcGVsaWEgc3VyYXRlbnNpcywgYW5kIFBhdGFnaW9lbmFzIGFsYmlwZW5uaXMgY29tYmluZWQuCgpDaGVjayB3aGV0aGVyIHdlIG5lZWQgdG8gbWFwIGVCaXJkIHNwZWNpZXMgbmFtZXMgdG8gQmlyZGxpZmUKYGBge3J9CnRheG9ubW9taWNfbWFwcGluZ1t0YXhvbm1vbWljX21hcHBpbmckZWJpcmRfc3BlY2llc19uYW1lICVpbiUgc3BlY2llc19hdmFpbGFibGUsXSAlPiUKICBmaWx0ZXIoZWJpcmRfc3BlY2llc19uYW1lICE9IHNwZWNpZXNfbmFtZSkgCmBgYAoKU3BlY2llcyB3aXRoIDEgQmlyZGxpZmUgdGF4YSwgYW5kIG11bHRpcGxlIGVCaXJkIHRheGEgd2lsbCwgd291bGQgbWVhbiB0aGF0IHdlIHdvdWxkIGhhdmUgY2l0aWVzIHdpdGggbm8gcmVjb3JkcyBidXQgcG90ZW50aWFsbHkgaGF2ZSBwcmVzZW5jZSB0ZXN0IGRhdGEuIFdlIHNob3VsZCBhdm9pZCB0aGVzZSBzcGVjaWVzLgpgYGB7cn0KdGF4b25tb21pY19tYXBwaW5nW3RheG9ubW9taWNfbWFwcGluZyRlYmlyZF9zcGVjaWVzX25hbWUgJWluJSBzcGVjaWVzX2F2YWlsYWJsZSxdICU+JQogIGdyb3VwX2J5KHNwZWNpZXNfbmFtZSkgJT4lIAogIHN1bW1hcmlzZShudW1iZXJfb2ZfZWJpcmRfc3BlY2llcyA9IG4oKSwgZWJpcmRfc3BlY2llc19uYW1lcyA9IHBhc3RlKGViaXJkX3NwZWNpZXNfbmFtZSwgY29sbGFwc2UgPSAiLCIpKSAlPiUKICBmaWx0ZXIobnVtYmVyX29mX2ViaXJkX3NwZWNpZXMgPiAxKQpgYGAKCmBgYHtyfQp0ZXN0X3NwZWNpZXMgPSBzcGVjaWVzX2F2YWlsYWJsZQpgYGAKCiMgQ3JlYXRlIHJlZ2lvbmFsIHBvb2wgZGF0YSAKYGBge3J9CnJlZ2lvbmFsX3Bvb2xfZGF0YV9pbnB1dCA9IHJlYWRfY3N2KGZpbGVuYW1lKEJJUkRMSUZFX1dPUktJTkdfT1VUUFVUX0RJUiwgJ3VyYmFuX2Rpc3RyaWJ1dGlvbnMuY3N2JykpCmBgYApgYGB7cn0KdGF4b25tb21pY19tYXBwaW5nW3RheG9ubW9taWNfbWFwcGluZyRlYmlyZF9zcGVjaWVzX25hbWUgPT0gJ1NwaWxvcGVsaWEgY2hpbmVuc2lzJyxdCmBgYAoKYGBge3J9CnRheG9ubW9taWNfbWFwcGluZ1t0YXhvbm1vbWljX21hcHBpbmckZWJpcmRfc3BlY2llc19uYW1lID09ICdQYXRhZ2lvZW5hcyBmYXNjaWF0YScsXQpgYGAKSm9pbiByYW5nZXMgdXAgCmBgYHtyfQpyZWdpb25hbF9wb29sX2RhdGFfaW5wdXQkc3BlY2llc19uYW1lW3JlZ2lvbmFsX3Bvb2xfZGF0YV9pbnB1dCRzcGVjaWVzX25hbWUgJWluJSBjKCdTcGlsb3BlbGlhIHN1cmF0ZW5zaXMnLCAnUGF0YWdpb2VuYXMgYWxiaXBlbm5pcycpXSA9ICdTcGlsb3BlbGlhIGNoaW5lbnNpcycKcmVnaW9uYWxfcG9vbF9kYXRhX2lucHV0JHNwZWNpZXNfbmFtZVtyZWdpb25hbF9wb29sX2RhdGFfaW5wdXQkc3BlY2llc19uYW1lICVpbiUgYygnUGF0YWdpb2VuYXMgYWxiaWxpbmVhJyldID0gJ1BhdGFnaW9lbmFzIGZhc2NpYXRhJwoKcmVnaW9uYWxfcG9vbF9kYXRhID0gcmVnaW9uYWxfcG9vbF9kYXRhX2lucHV0ICU+JSBncm91cF9ieShzcGVjaWVzX25hbWUsIGNpdHlfaWQsIGNpdHlfbmFtZSkgJT4lIHN1bW1hcmlzZSgpICU+JSBmaWx0ZXIoc3BlY2llc19uYW1lICVpbiUgdGVzdF9zcGVjaWVzKQpyZWdpb25hbF9wb29sX2RhdGFbcmVnaW9uYWxfcG9vbF9kYXRhJGNpdHlfbmFtZSA9PSAnTWVkZWxsw61uJyxdCmBgYAoKIyBEb3dubG9hZCBTdGF0dXMgYW5kIFRyZW5kcyBkYXRhCmBgYHtyfQprZXkgPSByZWFkX2ZpbGUoZmlsZW5hbWUoS0VZU19ESVIsICdlYmlyZHN0LnR4dCcpKQpzZXRfZWJpcmRzdF9hY2Nlc3Nfa2V5KGtleSwgb3ZlcndyaXRlID0gVCkKZWJpcmRzdF9kYXRhX2RpcigpCmBgYAoKYGBge3J9CmZvciAoc3BlY2llcyBpbiB0ZXN0X3NwZWNpZXMpIHsKICBwcmludChwYXN0ZSgnZmV0Y2hpbmcnLCBzcGVjaWVzKSkKICBlYmlyZHN0X2Rvd25sb2FkX3N0YXR1cygKICAgIHNwZWNpZXMgPSBzcGVjaWVzLAogICAgZG93bmxvYWRfYWJ1bmRhbmNlID0gVFJVRSwKICAgIGRvd25sb2FkX29jY3VycmVuY2UgPSBGQUxTRSwKICAgIGRvd25sb2FkX2NvdW50ID0gRkFMU0UsCiAgICBkb3dubG9hZF9yYW5nZXMgPSBGQUxTRSwKICAgIGRvd25sb2FkX3JlZ2lvbmFsID0gRkFMU0UsCiAgICBkb3dubG9hZF9waXMgPSBGQUxTRSwKICAgIGRvd25sb2FkX3BwbXMgPSBGQUxTRSwKICAgIGRvd25sb2FkX2FsbCA9IEZBTFNFCiAgKQp9CmBgYAoKIyMgQ2FsY3VsYXRlIGFidW5kYW5jZSBmb3IgZWFjaCBjaXR5ClJlYWQgaW4gb3VyIGluaXRpYWwgY2l0eSB2ZWN0b3JzLCB3ZSB3aWxsIGpvaW4gdGhlc2UgdG8gb3VyIGNoZWNrbGlzdHMKYGBge3J9CmluaXRpYWxfY2l0eV9zZWxlY3Rpb24gPSB2ZWN0KGZpbGVuYW1lKG1rZGlyKEdFT19XT1JLSU5HX09VVFBVVF9ESVIsICdjaXRpZXMnKSwgJ2luaXRpYWxfc2VsZWN0aW9uLnNocCcpKQpgYGAKCmBgYHtyfQpjaXR5X2RhdGEgPSBkYXRhLmZyYW1lKGluaXRpYWxfY2l0eV9zZWxlY3Rpb24pCmNpdHlfZGF0YSRJRCA9IGFzLmRvdWJsZShyb3duYW1lcyhjaXR5X2RhdGEpKQpjaXR5X2RhdGEKYGBgCgpgYGB7cn0KYWJ1bmRhbmNlX2RhdGEgPSBkYXRhLmZyYW1lKCkKCmZvciAoc3BlY2llcyBpbiB0ZXN0X3NwZWNpZXMpIHsKICBhYmQgPC0gbG9hZF9yYXN0ZXIoc3BlY2llcywgcmVzb2x1dGlvbiA9ICIza20iLCBwcm9kdWN0ID0gImFidW5kYW5jZSIsIHBlcmlvZCA9ICJzZWFzb25hbCIpCiAgYWJkX3dnczg0ID0gcHJvamVjdChhYmQsIGluaXRpYWxfY2l0eV9zZWxlY3Rpb24pCiAgY2l0eV9hYnVuZGFuY2UgPSB0ZXJyYTo6ZXh0cmFjdChhYmRfd2dzODQsIGluaXRpYWxfY2l0eV9zZWxlY3Rpb24pCiAgCiAgaWYgKCJyZXNpZGVudCIgJWluJSBjb2xuYW1lcyhjaXR5X2FidW5kYW5jZSkpIHsKICAgICByZXN1bHQgPSBjaXR5X2FidW5kYW5jZSAlPiUgZ3JvdXBfYnkoSUQpICU+JSBzdW1tYXJpc2UoCiAgICAgICBicmVlZGluZyA9IE5BLCAKICAgICAgIG5vbmJyZWVkaW5nID0gTkEsIAogICAgICAgcmVzaWRlbnQgPSBtZWFuKHJlc2lkZW50KSwgCiAgICAgICBzcGVjaWVzID0gc3BlY2llcwogICAgICkKICAgICBhYnVuZGFuY2VfZGF0YSA9IHJiaW5kKGFidW5kYW5jZV9kYXRhLCBpbm5lcl9qb2luKHJlc3VsdCwgY2l0eV9kYXRhWyxjKCdJRCcsICdjaXR5X2lkJywgJ2NpdHlfbmFtZScpXSkpCiAgfSBlbHNlIHsKICAgIHJlc3VsdCA9IGNpdHlfYWJ1bmRhbmNlICU+JSBncm91cF9ieShJRCkgJT4lIHN1bW1hcmlzZSgKICAgICAgYnJlZWRpbmcgPSBtZWFuKGJyZWVkaW5nKSwgCiAgICAgIG5vbmJyZWVkaW5nID0gbWVhbihub25icmVlZGluZyksIAogICAgICByZXNpZGVudCA9IE5BLCAKICAgICAgc3BlY2llcyA9IHNwZWNpZXMKICAgICkgCiAgICBhYnVuZGFuY2VfZGF0YSA9IHJiaW5kKGFidW5kYW5jZV9kYXRhLCBpbm5lcl9qb2luKHJlc3VsdCwgY2l0eV9kYXRhWyxjKCdJRCcsICdjaXR5X2lkJywgJ2NpdHlfbmFtZScpXSkpCiAgfQp9CgphYnVuZGFuY2VfZGF0YVthYnVuZGFuY2VfZGF0YSRjaXR5X25hbWUgPT0gJ01hbmNoZXN0ZXInLF0KYGBgCgpgYGB7cn0Kd3JpdGVfY3N2KGFidW5kYW5jZV9kYXRhLCBmaWxlbmFtZShFQklSRF9XT1JLSU5HX09VVFBVVF9ESVIsICdlYmlyZF90cmVuZHNfYWJ1bmRhbmNlX3Rlc3RfZGF0YS5jc3YnKSkKYWJ1bmRhbmNlX2RhdGEgPSByZWFkX2NzdihmaWxlbmFtZShFQklSRF9XT1JLSU5HX09VVFBVVF9ESVIsICdlYmlyZF90cmVuZHNfYWJ1bmRhbmNlX3Rlc3RfZGF0YS5jc3YnKSkKYGBgCgpgYGB7cn0KYWJ1bmRhbmNlX2RhdGEkbWF4X2FidW5kYW5jZSA9IGFwcGx5KGFidW5kYW5jZV9kYXRhWyxjKCdicmVlZGluZycsICdub25icmVlZGluZycsICdyZXNpZGVudCcpXSwgMSwgbWF4LCBuYS5ybSA9IFQpCmFidW5kYW5jZV9kYXRhJG1heF9hYnVuZGFuY2VbYWJ1bmRhbmNlX2RhdGEkbWF4X2FidW5kYW5jZSA9PSAtSW5mXSA9IE5BCmFidW5kYW5jZV9kYXRhW2FidW5kYW5jZV9kYXRhJGNpdHlfbmFtZSA9PSAnTWFuY2hlc3RlcicsXQpgYGAKYGBge3J9CmFidW5kYW5jZV9kYXRhW2FidW5kYW5jZV9kYXRhJGNpdHlfbmFtZSA9PSAnTWVkZWxsw61uJyxdCmBgYAoKRmlsdGVyIHRvIHJlZ2lvbmFsIHBvb2xzCmBgYHtyfQphYnVuZGFuY2VfZGF0YV9yZWdpb25hbCA9IGxlZnRfam9pbihyZWdpb25hbF9wb29sX2RhdGEsIGFidW5kYW5jZV9kYXRhLCBieSA9IGMoJ2NpdHlfaWQnID0gJ2NpdHlfaWQnLCAnY2l0eV9uYW1lJyA9ICdjaXR5X25hbWUnLCAnc3BlY2llc19uYW1lJyA9ICdzcGVjaWVzJykpCmFidW5kYW5jZV9kYXRhX3JlZ2lvbmFsW2FidW5kYW5jZV9kYXRhX3JlZ2lvbmFsJGNpdHlfbmFtZSA9PSAnTWFuY2hlc3RlcicsXQpgYGAKCmBgYHtyfQphYnVuZGFuY2VfZGF0YV9yZWdpb25hbFthYnVuZGFuY2VfZGF0YV9yZWdpb25hbCRjaXR5X25hbWUgPT0gJ01lZGVsbMOtbicsXQpgYGAKCkFyZSBhbnkgc3BlY2llcyBub3cgbWlzc2luZyB0aGF0IGFyZSBhYnVuZGFudD8KYGBge3J9CmNpdHlfaWRfc3BlY2llc19wYWlyc19wcmVzZW50ID0gcGFzdGUoYWJ1bmRhbmNlX2RhdGFfcmVnaW9uYWwkc3BlY2llc19uYW1lLCBhYnVuZGFuY2VfZGF0YV9yZWdpb25hbCRjaXR5X2lkLCBzZXAgPSAnOjonKQphYnVuZGFuY2VfZGF0YSAlPiUgCiAgZmlsdGVyKG1heF9hYnVuZGFuY2UgPiAwKSAlPiUgCiAgZ3JvdXBfYnkoY2l0eV9pZCwgc3BlY2llcykgJT4lIAogIGZpbHRlcighKHBhc3RlKHNwZWNpZXMsIGNpdHlfaWQsIHNlcCA9ICc6OicpICVpbiUgY2l0eV9pZF9zcGVjaWVzX3BhaXJzX3ByZXNlbnQpKQpgYGAKCiMgQ3JlYXRlIGNpdHkgdG8gcGlnZW9uIGRhdGEKCkdldCBudW1iZXIgb2YgY2hlY2tsaXN0cyBhbmQgdG90YWwgZWZmb3J0IGluIGVhY2ggY2l0eQpgYGB7cn0KdXJiYW5fY2hlY2tsaXN0cyA9IHJlYWRfY3N2KGZpbGVuYW1lKEVCSVJEX1dPUktJTkdfT1VUUFVUX0RJUiwgJ3VyYmFuX2NoZWNrbGlzdHMuY3N2JykpCgp1cmJhbl9zdW1tYXJ5ID0gdXJiYW5fY2hlY2tsaXN0cyAlPiUgZ3JvdXBfYnkoY2l0eV9pZCwgY2l0eV9uYW1lKSAlPiUgc3VtbWFyaXNlKHRvdGFsX2NpdHlfY2hlY2tsaXN0cyA9IG4oKSwgdG90YWxfY2l0eV9lZmZvcnQgPSBzdW0oZHVyYXRpb24pKQoKdXJiYW5fc3VtbWFyeQpgYGAKCgpGb3IgZWFjaCBvZiBvdXIgdGVzdCBzcGVjaWVzLCBmaW5kIHRoZSBudW1iZXIgb2YgY2hlY2tsaXN0cyBhbmQgdG90YWwgZWZmb3J0IGluIGVhY2ggY2l0eQpgYGB7cn0KdXJiYW5fY29sdW1iaWRhZV9yZWNvcmRzX3JhdyA9IHJlYWRfY3N2KGZpbGVuYW1lKEVCSVJEX1dPUktJTkdfT1VUUFVUX0RJUiwgJ3VyYmFuX2NvbHVtYmlkYWUuY3N2JykpCnVyYmFuX2NvbHVtYmlkYWVfcmVjb3Jkc19yYXdbdXJiYW5fY29sdW1iaWRhZV9yZWNvcmRzX3JhdyRjaXR5X25hbWUgPT0gJ01hbmNoZXN0ZXInLF0KYGBgCgpgYGB7cn0KdXJiYW5fY29sdW1iaWRhZV9yZWNvcmRzX3dpdGhfY2hlY2tsaXN0X2RhdGEgPSBsZWZ0X2pvaW4odXJiYW5fY29sdW1iaWRhZV9yZWNvcmRzX3JhdywgdGF4b25tb21pY19tYXBwaW5nLCBieSA9IGMoJ3NwZWNpZXNfbmFtZScgPSAnZWJpcmRfc3BlY2llc19uYW1lJykpCnVyYmFuX2NvbHVtYmlkYWVfcmVjb3Jkc193aXRoX2NoZWNrbGlzdF9kYXRhW3VyYmFuX2NvbHVtYmlkYWVfcmVjb3Jkc193aXRoX2NoZWNrbGlzdF9kYXRhJGNpdHlfbmFtZSA9PSAnTWFuY2hlc3RlcicsIF0KYGBgCgpgYGB7cn0KdXJiYW5fY29sdW1iaWRhZV9zdW1tYXJ5ID0gdXJiYW5fY29sdW1iaWRhZV9yZWNvcmRzX3dpdGhfY2hlY2tsaXN0X2RhdGEgJT4lIAogIGZpbHRlcihzcGVjaWVzX25hbWUueSAlaW4lIHRlc3Rfc3BlY2llcykgJT4lCiAgZ3JvdXBfYnkoY2l0eV9pZCwgY2l0eV9uYW1lLCBzcGVjaWVzX25hbWUueSkgJT4lIAogIHN1bW1hcmlzZSh0b3RhbF9wcmVzZW5jZV9jaGVja2xpc3RzID0gbigpLCB0b3RhbF9wcmVzZW5jZV9lZmZvcnQgPSBzdW0oZHVyYXRpb24pKSAlPiUKICBhcnJhbmdlKGNpdHlfaWQsIHNwZWNpZXNfbmFtZS55KQoKbmFtZXModXJiYW5fY29sdW1iaWRhZV9zdW1tYXJ5KSA9IGMoJ2NpdHlfaWQnLCAnY2l0eV9uYW1lJywgJ3NwZWNpZXNfbmFtZScsICd0b3RhbF9wcmVzZW5jZV9jaGVja2xpc3RzJywgJ3RvdGFsX3ByZXNlbmNlX2VmZm9ydCcpCnVyYmFuX2NvbHVtYmlkYWVfc3VtbWFyeVt1cmJhbl9jb2x1bWJpZGFlX3N1bW1hcnkkY2l0eV9uYW1lID09ICdNYW5jaGVzdGVyJyxdCmBgYAoKSm9pbiB0aGUgdG90YWwgY2l0eSBkYXRhIHRvIGVhY2ggcGlnZW9uIHJlY29yZApgYGB7cn0KdXJiYW5fY29sdW1iaWRhZV9yZWNvcmRzID0gbGVmdF9qb2luKHVyYmFuX2NvbHVtYmlkYWVfc3VtbWFyeSwgdXJiYW5fc3VtbWFyeSkKaGVhZCh1cmJhbl9jb2x1bWJpZGFlX3JlY29yZHMpCmBgYAoKYGBge3J9CnVyYmFuX2NvbHVtYmlkYWVfcmVjb3Jkc1t1cmJhbl9jb2x1bWJpZGFlX3JlY29yZHMkY2l0eV9uYW1lID09ICdNYW5jaGVzdGVyJyxdCmBgYAoKV2UgYWxzbyB3YW50IHJlY29yZHMgZm9yIGVhY2ggY2l0eSB0aGF0IGNvdWxkIGhhdmUgdGhhdCBwaWdlb24gKGUuZy4gaW4gcmVnaW9uYWwgcG9vbCByYW5nZSkgYnV0IGhhcyBubyBlQmlyZCByZWNvcmRzCmBgYHtyfQp1cmJhbl9jb2x1bWJpZGFlX2Fic2VuY2VfcmVjb3Jkc19wYXJ0MSA9IGxlZnRfam9pbihyZWdpb25hbF9wb29sX2RhdGEsIHVyYmFuX3N1bW1hcnkpCgp1cmJhbl9jb2x1bWJpZGFlX2Fic2VuY2VfcmVjb3Jkc19wYXJ0MSR0b3RhbF9wcmVzZW5jZV9jaGVja2xpc3RzID0gMAp1cmJhbl9jb2x1bWJpZGFlX2Fic2VuY2VfcmVjb3Jkc19wYXJ0MSR0b3RhbF9wcmVzZW5jZV9lZmZvcnQgPSAwCgp1cmJhbl9jb2x1bWJpZGFlX2Fic2VuY2VfcmVjb3JkcyA9IHVyYmFuX2NvbHVtYmlkYWVfYWJzZW5jZV9yZWNvcmRzX3BhcnQxWyFpcy5uYSh1cmJhbl9jb2x1bWJpZGFlX2Fic2VuY2VfcmVjb3Jkc19wYXJ0MSR0b3RhbF9jaXR5X2NoZWNrbGlzdHMpLF0KdXJiYW5fY29sdW1iaWRhZV9hYnNlbmNlX3JlY29yZHMKYGBgCgpgYGB7cn0KYWxsX2NvbHVtYmlkYWVfYXJvdW5kX2NpdGllcyA9IHJiaW5kKHVyYmFuX2NvbHVtYmlkYWVfcmVjb3JkcywgdXJiYW5fY29sdW1iaWRhZV9hYnNlbmNlX3JlY29yZHMpICU+JQogIGdyb3VwX2J5KGNpdHlfaWQsIGNpdHlfbmFtZSwgc3BlY2llc19uYW1lLCB0b3RhbF9jaXR5X2NoZWNrbGlzdHMsIHRvdGFsX2NpdHlfZWZmb3J0KSAlPiUKICBzdW1tYXJpc2UodG90YWxfcHJlc2VuY2VfY2hlY2tsaXN0cyA9IHN1bSh0b3RhbF9wcmVzZW5jZV9jaGVja2xpc3RzKSwgdG90YWxfcHJlc2VuY2VfZWZmb3J0ID0gc3VtKHRvdGFsX3ByZXNlbmNlX2VmZm9ydCkpICU+JQogIGFycmFuZ2UoY2l0eV9pZCwgc3BlY2llc19uYW1lKQoKYWxsX2NvbHVtYmlkYWVfYXJvdW5kX2NpdGllcyRjaGVja2xpc3RfcmF0aW8gPSBhbGxfY29sdW1iaWRhZV9hcm91bmRfY2l0aWVzJHRvdGFsX3ByZXNlbmNlX2NoZWNrbGlzdHMgLyBhbGxfY29sdW1iaWRhZV9hcm91bmRfY2l0aWVzJHRvdGFsX2NpdHlfY2hlY2tsaXN0cwphbGxfY29sdW1iaWRhZV9hcm91bmRfY2l0aWVzJGVmZm9ydF9yYXRpbyA9IGFsbF9jb2x1bWJpZGFlX2Fyb3VuZF9jaXRpZXMkdG90YWxfcHJlc2VuY2VfZWZmb3J0IC8gYWxsX2NvbHVtYmlkYWVfYXJvdW5kX2NpdGllcyR0b3RhbF9jaXR5X2VmZm9ydAoKYWxsX2NvbHVtYmlkYWVfYXJvdW5kX2NpdGllcwpgYGAKCkZpbmFsbHkgam9pbiBvdXIgb3VyIHRlc3QgZGF0YSByZXN1bHQgdG8gc2hvdyBwcmVkaWN0ZWQgYWJ1bmRhbmNlLCByZW1vdmUgYW55IE5BIGFidW5kYW5jZSBhcyB0aGVyZSBpcyBpbnN1ZmZpY2VudCBkYXRhIGluIHRoZXNlIHBsYWNlcyBmb3IgYSBwcmVkaWN0aW9uLgpgYGB7cn0KY29sdW1iaWRhZSA9IGxlZnRfam9pbihhbGxfY29sdW1iaWRhZV9hcm91bmRfY2l0aWVzLCBhYnVuZGFuY2VfZGF0YSwgYnkgPSBjKCdzcGVjaWVzX25hbWUnID0gJ3NwZWNpZXMnLCAnY2l0eV9pZCcgPSAnY2l0eV9pZCcsICdjaXR5X25hbWUnID0gJ2NpdHlfbmFtZScpKQpjb2x1bWJpZGFlID0gY29sdW1iaWRhZVshaXMubmEoY29sdW1iaWRhZSRtYXhfYWJ1bmRhbmNlKSxjKCdjaXR5X2lkJywgJ2NpdHlfbmFtZScsICdzcGVjaWVzX25hbWUnLCAndG90YWxfY2l0eV9jaGVja2xpc3RzJywgJ3RvdGFsX3ByZXNlbmNlX2NoZWNrbGlzdHMnLCAnY2hlY2tsaXN0X3JhdGlvJywgJ21heF9hYnVuZGFuY2UnKV0KY29sdW1iaWRhZSRleHBlY3RlZF9wcmVzZW50ID0gY29sdW1iaWRhZSRtYXhfYWJ1bmRhbmNlID4gMC4xCmNvbHVtYmlkYWUKYGBgCgojIFBsb3QgdG8gc2VlIEV4cGVjdGVkIHRlc3QgYWJ1bmRhbmNlIHZzIGNoZWNrbGlzdHMKYGBge3J9CmdncGxvdChjb2x1bWJpZGFlW2NvbHVtYmlkYWUkc3BlY2llc19uYW1lID09ICdDb2x1bWJhIHBhbHVtYnVzJyxdLCBhZXMoeSA9IGNoZWNrbGlzdF9yYXRpbywgeCA9IG1heF9hYnVuZGFuY2UsIGNvbG9yID0gbG9nKHRvdGFsX2NpdHlfY2hlY2tsaXN0cykpKSArIGdlb21faml0dGVyKCkgKyBnZW9tX2ppdHRlcigpICsgc2NhbGVfY29sb3VyX2dyYWRpZW50MigKICBsb3cgPSAicmVkIiwKICBtaWQgPSAieWVsbG93IiwKICBoaWdoID0gImRhcmtncmVlbiIsCiAgbWlkcG9pbnQgPSBsb2coMTAwKSwKICBzcGFjZSA9ICJMYWIiLAogIG5hLnZhbHVlID0gImdyZXk1MCIsCiAgZ3VpZGUgPSAiY29sb3VyYmFyIiwKICBhZXN0aGV0aWNzID0gImNvbG91ciIsCikKYGBgCgpuID0gKChaICogWikgKiBwICogKDHiiJJwKSkgLyAoRSAqIEUpCgooZS5nLiwgOTklIGNvcnJlc3BvbmRzIHRvIFriiYgyLjU3NlriiYgyLjU3NikuCiAKU28gZm9yIHByZXNlbnQgPSBtb3JlIHRoYW4gNSUgb2YgY2hlY2tsaXN0cy4KCnAgaXMgdGhlIGVzdGltYXRlZCBwcm9iYWJpbGl0eSBvZiBzdWNjZXNzICh0aGUgcHJvcG9ydGlvbiBvZiBjaGVja2xpc3RzIHdoZXJlIHRoZSBzcGVjaWVzIGlzIHByZXNlbnQpLgpFIGlzIHRoZSBtYXJnaW4gb2YgZXJyb3IgKGhhbGYgdGhlIHdpZHRoIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFsKS4KCmBgYHtyfQooMi41NzZeMiAqIDAuOTUgKiAwLjA1KSAvIDAuMDFeMgpgYGAKCmBgYHtyfQp1cmJhbl9zdW1tYXJ5W3VyYmFuX3N1bW1hcnkkdG90YWxfY2l0eV9jaGVja2xpc3RzID4gMzE1MixdCmBgYAoKYGBge3J9CnBsb3RfY2l0eV9zcGVjaWVzID0gZnVuY3Rpb24oY2l0eV9pZCkgewogIGNpdHlfbmFtZSA9IHVyYmFuX3N1bW1hcnkkY2l0eV9uYW1lW3VyYmFuX3N1bW1hcnkkY2l0eV9pZCA9PSBjaXR5X2lkXQogIHRvdGFsX2NoZWNrbGlzdHMgPSB1cmJhbl9zdW1tYXJ5JHRvdGFsX2NpdHlfY2hlY2tsaXN0c1t1cmJhbl9jaGVja2xpc3RzJGNpdHlfaWQgPT0gY2l0eV9pZF0KICAKICBnZ3Bsb3QoY29sdW1iaWRhZVtjb2x1bWJpZGFlJGNpdHlfaWQgPT0gY2l0eV9pZCxdLCBhZXMoeCA9IHNwZWNpZXNfbmFtZSwgeSA9IGNoZWNrbGlzdF9yYXRpbyAqIDEwMCwgZmlsbCA9IGV4cGVjdGVkX3ByZXNlbnQpKSArIAogICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsgCiAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQobWF4X2FidW5kYW5jZSwgMikpKSArIAogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0PTEpKSArIAogICAgeGxhYignU3BlY2llcyBuYW1lJykgKyB5bGFiKCclIG9mIENoZWNrbGlzdCBwcmVzZW50JykgKyAKICAgIGZhY2V0X3dyYXAofmNpdHlfaWQpICsgCiAgICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9NSwgbGluZXR5cGU9J2RvdHRlZCcsIGNvbCA9ICdyZWQnKSArCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoY2l0eV9uYW1lLCB0b3RhbF9jaGVja2xpc3RzKSkKfQpgYGAKCmBgYHtyfQpwbG90X2NpdHlfc3BlY2llcygxKQpgYGAKCmBgYHtyfQpwbG90X2NpdHlfc3BlY2llcygxMCkKYGBgCgpgYGB7cn0KcGxvdF9jaXR5X3NwZWNpZXMoMTQpCmBgYAoKYGBge3J9CnBsb3RfY2l0eV9zcGVjaWVzKDIxKQpgYGAKCmBgYHtyfQpwbG90X2NpdHlfc3BlY2llcygxNTUpCmBgYAoKYGBge3J9CnBsb3RfY2l0eV9zcGVjaWVzKDc5MzIpCmBgYAoKYGBge3J9CnBsb3RfY2l0eV9zcGVjaWVzKDQzMjgpCmBgYAoKYGBge3J9CnBsb3RfY2l0eV9zcGVjaWVzKDE5MTkpCmBgYAoKYGBge3J9CnBsb3RfY2l0eV9zcGVjaWVzKDEzMDgpCmBgYAoKCg==